import random
from web import models
from django import forms
from django.core.validators import RegexValidator
from django.core.exceptions import ValidationError
from django_redis import get_redis_connection
from tracer import settings
from web.forms.bootstrap import BootstrapForm
import redis
from utils.encrypt import md5
from utils.tencent.sms import send_sms_single


class RegisterModelForm(BootstrapForm, forms.ModelForm):
    phone = forms.CharField(label='手机号', validators=[RegexValidator(r'^1[3,5,7-9]\d{9}$', '手机号格式错误，请检查')])
    password = forms.CharField(
        label='密码',
        min_length=8,
        max_length=64,
        error_messages={
            'min_length': "密码长度不能小于8个字符",
            'max_length': "密码长度不能大于64个字符"
        },
        widget=forms.PasswordInput()
    )

    confirm_password = forms.CharField(
        label='重复密码',
        min_length=8,
        max_length=64,
        error_messages={
            'min_length': "重复密码长度不能小于8个字符",
            'max_length': "重复密码长度不能大于64个字符"
        },
        widget=forms.PasswordInput())

    code = forms.CharField(label='验证码')

    class Meta:
        model = models.UserInfo
        fields = '__all__'

    def clean_username(self):
        username = self.cleaned_data['username']
        exist = models.UserInfo.objects.filter(username=username).exists()
        if exist:
            raise ValidationError('用户名已存在')
        return username

    def clean_email(self):
        email = self.cleaned_data['email']
        exist = models.UserInfo.objects.filter(email=email).exists()
        if exist:
            raise ValidationError('该邮箱已存在')
        return email

    def clean_phone(self):
        phone = self.cleaned_data['phone']
        exist = models.UserInfo.objects.filter(phone=phone).exists()
        if exist:
            raise ValidationError('手机号已存在')
        return phone

    def clean_password(self):
        pwd = self.cleaned_data.get('password')
        return md5(pwd)

    def clean_confirm_password(self):
        pwd = self.cleaned_data.get('password')
        confirm = md5(self.cleaned_data.get('confirm_password'))
        if confirm != pwd:
            raise ValidationError('两次输入密码不一致')
        return confirm

    def clean_code(self):
        clean_code = self.cleaned_data.get('code')
        phone = self.cleaned_data.get('phone')
        if not phone:
            raise ValidationError('请输入手机号')
        # if not clean_code:
        #     raise ValidationError('请输入验证码！')
        # print(self.cleaned_data.get('phone'))
        conn = get_redis_connection()
        try:
            code = bytes.decode(conn.get(self.cleaned_data.get('phone')))
        except:
            code = None

        # print('clean_code is:', clean_code, 'code is:', code)

        if not code:
            raise ValidationError('验证码已超时，请重新获取')
        if clean_code != code:
            raise ValidationError('验证码错误，请重新输入')
        return code


class LoginModelForm(BootstrapForm, forms.ModelForm):
    phone = forms.CharField(label='手机号', validators=[RegexValidator(r'^1[3,5,7-9]\d{9}$', '手机号格式错误，请检查')])
    code = forms.CharField(label='短信验证码')

    class Meta:
        model = models.UserInfo
        fields = ['phone', 'code']

    def clean_code(self):
        conn = get_redis_connection()
        try:
            code = bytes.decode(conn.get(self.cleaned_data.get('phone')))
        except:
            code = None
        clean_code = self.cleaned_data.get('code')
        if not code:
            raise ValidationError('请先获取验证码')
        if clean_code != code:
            raise ValidationError('验证码错误，请重新输入')
        return code


class UserLoginModelForm(BootstrapForm, forms.Form):
    username = forms.CharField(label='手机号或邮箱')
    password = forms.CharField(label='密码', widget=forms.PasswordInput(render_value=True))
    code = forms.CharField(label='验证码')

    def __init__(self, request, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.request = request

    def clean_code(self):
        code = self.cleaned_data['code']

        session_code = self.request.session['image_code']
        if not session_code:
            raise ValidationError('验证码已过期，请重新获取')

        if session_code.strip().upper() != code.strip().upper():
            raise ValidationError('验证码输入错误')
        return code

    def clean_password(self):
        return md5(self.cleaned_data['password'])


class SendSmsForm(forms.Form):
    username = forms.CharField(label='用户名', required=False)
    email = forms.CharField(label='邮箱', required=False)
    phone = forms.CharField(label='手机号', validators=[RegexValidator(r'^1[3,5,7-9]\d{9}$', '手机号格式错误，请检查')])

    def __init__(self, request, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.request = request

    def clean_username(self):
        username = self.request.GET.get('username')
        tpl = self.request.GET.get('tpl')
        if tpl == 'login':
            return None
        exist = models.UserInfo.objects.filter(username=username).exists()
        if exist:
            self.add_error('username', '用户名已存在')

    def clean_email(self):
        email = self.request.GET.get('email')
        tpl = self.request.GET.get('tpl')
        if tpl == 'login':
            return None
        exist = models.UserInfo.objects.filter(email=email).exists()
        if exist:
            self.add_error('email', '该邮箱已存在')

    def clean_phone(self):
        phone = self.cleaned_data['phone']

        # 判断短信模板
        tpl = self.request.GET.get('tpl')
        template_id = settings.TENCENT_SMS_TEMPLATE.get(tpl)
        if not template_id:
            raise ValidationError('短信模板错误')

        exist = models.UserInfo.objects.filter(phone=phone).exists()
        # 获取验证码
        code = random.randrange(1000, 9999)

        # 校验手机号
        if tpl == 'register':
            template_params = [code, ]
            if exist:
                raise ValidationError('手机号已存在')
        else:
            template_params = [code, 1]
            if not exist:
                raise ValidationError('手机号不存在')

        # 发送短信
        #sms = send_sms_single(phone, template_id, template_params)
        #if sms['result'] != 0:
        #    self.add_error('phone', '短信发送失败， {}'.format(sms['errmsg']))

        # 写入redis
        conn = get_redis_connection()
        conn.set(phone, code, ex=60)
        return phone


